home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
polyview
/
polyvw31.lha
/
Polyview3.1
/
new
/
pvvset.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-13
|
32KB
|
1,074 lines
/*****************************************************************************
* NCSA Polyview 3.1 *
* *
* Version 3.1 changes and additions by Gilles Bourhis *
* Version 3 changes and additions by Marc Andreessen. *
* Version 2 by Brian Calvert. *
* *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* *
* This is BETA release software. As such it may contain software bugs and *
* exhibit inconsistencies. *
* *
* Please send bug reports to polyview@ncsa.uiuc.edu. *
* *
* Copyright (c) 1992 The Board of Trustees of the University of Illinois. *
* *
* Permission to use, copy, and modify this software and its *
* documentation for educational, research, and non-profit purposes is *
* hereby granted, provided that the above copyright notice, the original *
* authors names, and this permission notice appear in all such copies. *
* Any distribution of this software requires the explicit and written *
* authorization of the authors. *
* *
* The University of Illinois makes no representations about the *
* suitability of this software for any purpose. It is provided "as is" *
* without warranty of any kind. *
*****************************************************************************/
/* $Id: pvvset.c,v 1.4 93/08/13 12:51:16 gbourhis Exp $ */
#ifdef RCSLOG
$Log: pvvset.c,v $
* Revision 1.4 93/08/13 12:51:16 gbourhis
* changes in set_file_dtm_explicit().
*
* Revision 1.3 93/07/13 16:47:25 gbourhis
* use file handle field, better testing of data type in swap_in().
*
* Revision 1.2 93/06/25 09:02:46 gbourhis
* Modifs needed to use HDF 3.2
*
* Revision 1.1 92/09/18 10:55:26 marca
* Initial revision
*
#endif
#include "pv.h"
static Vgroup_t *create_vgroup(state_t *state, int id, char *name)
{
Vgroup_t *new;
new = (Vgroup_t *) PVMALLOC(sizeof(Vgroup_t));
strcpy(new->name, name);
new->id = id;
new->children_read = FALSE;
new->sibling = NULL;
new->groups = NULL;
new->vdatas = NULL;
return new;
}
static files_t *create_file(state_t *state, int type, char *path)
{
files_t *new;
new = (files_t *) PVMALLOC(sizeof(files_t));
new->type = type;
strcpy(new->path, path);
/* Create dummy root group. */
new->groups = create_vgroup(state, -1, "/");
new->groups->file = new;
new->portid = DTMERROR;
new->vdatas = NULL;
new->next = NULL;
return new;
}
/* external */
Vdata_t *create_vdata(state_t *state, int id, char *name, files_t *source)
{
Vdata_t *new;
int i;
new = (Vdata_t *) PVMALLOC(sizeof(Vdata_t));
strcpy(new->name, name);
new->id = id;
new->file = source;
new->locked = FALSE;
new->in_memory = FALSE;
new->last_used = 0;
new->stats_read = FALSE;
new->sibling = NULL;
new->next = NULL;
for (i = 0; i < MAXDATADIMS; i++)
new->stats[i].rec_count = new->stats[i].rec_size = 0;
return new;
}
/* add_file creates a new in-memory file record and inserts it into the */
/* vset structure. Returns a pointer to the new file record. */
static files_t *add_file(state_t *state, int type, char *path)
{
files_t *new;
/* Create a new record for the file. */
new = create_file(state, type, path);
/* Link the file into the vset pool. */
new->next = state->files;
state->files = new;
return new;
}
files_t *set_file_dtm_explicit (state_t *state, char *path)
{
files_t *file;
for (file = STA_SOURCES(state); file != NULL; file = file->next)
if (file->type == DTMPORT && strcmp(file->path, path)==0)
break;
return (file == NULL) ? add_file (state, DTMPORT, path) : file;
}
static files_t *set_file(state_t *state, int type, char *path)
{
int vgid;
VGROUP *vghandle;
char name[MAXNAMELEN];
files_t *file;
FILE *fp;
/* Find the file's record in the vset pool. */
for (file = STA_SOURCES(state); file != NULL; file = file->next)
if (strcmp(file->path, path) == 0)
break;
/* Does the file exist in the vset pool? */
if (file == NULL)
{
/* File does not exist in the pool. Make sure that it exists */
/* on the disk before adding it to the vset pool. */
if (type != DTMPORT)
{
if ((fp = fopen(path, "r")) == NULL) {
/* The file either doesn't exist or is unreadable. */
/* Quit without making a change to the active file. */
stprintf (state, "ERROR: '%s' cannot be opened.\n", path);
return NULL;
}
fclose(fp);
}
file = add_file(state, type, path);
/* Initialize the state for the new file. */
switch (file->type)
{
/* What's the point of handling these? */
case HDFRIS8:
case HDFSDS:
if ((file->fh = Hopen(path, DFACC_READ, 0)) < 0)
return NULL;
break;
case HDFVSET:
if ((file->fh = Vopen(path, DFACC_READ, 0)) < 0)
return NULL;
/* If the root group id is not there, get it. */
if ((type == HDFVSET) && (file->groups->id == -1))
{
vgid = -1;
while ((vgid = Vgetid(file->fh, vgid)) != -1)
{
vghandle = Vattach(file->fh, vgid, "r");
Vgetname(vghandle, name);
Vdetach(vghandle);
if ((name[0] == '/') && (name[1] == '\0'))
{
/* Found root vgroup. */
file->groups->id = vgid;
break;
}
}
if (vgid == -1)
{
stprintf
(state,
"File does not contain '/' group; assuming all groups contained by root.");
}
}
break;
case UNIX:
fprintf(stderr, "ERROR: File type unsupported.\n");
fflush (stderr);
break;
case DTMPORT:
/* MARC: Added extra (dummy) parameter '0' to DTMmakeInPort;
DTM 2.0 source claims this is reserved for future use. */
COMdtm_in (state, path);
break;
default:
fprintf(stderr, "[set_file] SYSTEM ERROR: File type undefined.\n");
fflush (stderr);
break;
}
}
return file;
}
/* path parse splits a pathname into its filepath, vgroup path, and vdata */
/* name components, according to the pathtype passed to it. If any of the */
/* pieces are not found, the arrays passed to the function are not modified. */
/* Returns ST_OKAY if no errors occur. */
/* Breaks a fullpath name into file, vgroup, and vdata components according */
/* to its pathtype. Legal FILEPATH is composed of any characters except */
/* for a colon. A VGROUPPATH is of the form "[<filepath>:]<vgrouppath>". */
/* A VDATANAME is of the form "[<filepath>:][[vgrouppath>/]<vdataname>". */
/* Returns ST_OKAY if no errors occur. */
static int parse_path(state_t *state, char *fullpath, int pathtype,
char *filepath, char *vgrouppath, char *vdataname)
{
char *vg;
char *vd;
/* If there is a colon separator it denotes the break between the */
/* file pathname and the vgroup path. The last slash in the string */
/* may mark where the vdata name occurs. Set the colon to an null */
/* character and set vgp to point to the following substring. */
vg = strchr(fullpath, ':');
vd = strrchr(fullpath, '/');
if (vg != NULL)
{
*vg = '\0';
vg++;
}
/* If there is a last slash and the pathtype is a VDATANAME and the */
/* slash occurs after whatever vgroupname there is starts, then */
/* it is useful to break the vdataname off of the rest of the */
/* string. */
if ((vd != NULL) && (pathtype == VDATANAME) && (vd >= vg))
{
*vd = '\0';
vd++;
}
else
{
vd = NULL;
}
switch (pathtype)
{
case FILEPATH:
if (vg != NULL)
{
/* Colons are not allowed in file pathnames as they delimit */
/* group names. */
printf("ERROR: Colon in file path '%s:%s'\n", fullpath, vg);
return ST_ERROR;
}
strcpy(filepath, fullpath);
break;
case VGROUPPATH:
if (vg == NULL)
/* No file pathname, just group name. */
strcpy(vgrouppath, fullpath);
else
{
/* File pathname and groupname. */
strcpy(filepath, fullpath);
strcpy(vgrouppath, vg);
}
break;
case VDATANAME:
if (vg == NULL)
{
if (vd == NULL)
/* Just a VDATANAME, nothing else. */
vd = fullpath;
else
/* VDATANAME and a VGROUPPATH */
vg = fullpath;
}
else {
/* A filepath is included in this path */
strcpy(filepath, fullpath);
if (vd == NULL)
{
/* Just a VDATANAME after the filepath */
vd = vg;
vg = NULL;
}
}
/* Get the vdata name and group path name. */
strcpy(vdataname, vd);
if (vg != NULL)
strcpy(vgrouppath, vg);
break;
default:
fprintf(stderr, "[parse_path] SYSTEM ERROR: %d not valid pathtype.\n",
pathtype);
fflush (stderr);
break;
}
return ST_OKAY;
}
static int GetNextId(int32 f, VGROUP *vgptr, int id)
{
if (vgptr == NULL)
return Vgetid(f, id);
else
return Vgetnext(vgptr, id);
}
static int IsVgroup(VGROUP *vgptr, int id)
{
return (vgptr == NULL) ? TRUE : Visvg(vgptr, id);
}
static int IsVdata(VGROUP *vgptr, int id)
{
return (vgptr == NULL) ? TRUE : Visvs(vgptr, id);
}
/* ------------------------------------------------------------------------ */
/* --------------------------- PUBLIC ROUTINES ---------------------------- */
/* ------------------------------------------------------------------------ */
/* Returns a pointer to the vdata at fullpath. fullpath is the name of a */
/* vdata, which may include a filename or vgroup path. Returns NULL if an */
/* error occurs. */
Vdata_t *find_vdata(state_t *state, Vgroup_t *vg, char *vdataname)
{
Vdata_t *vdata;
assert (vg == NULL);
/* Now that the proper file and vgroup are set in the state, */
/* search for the vdata. */
for (vdata = VGR_VDATAS(vg); vdata; vdata = VDA_SIBLING(vdata))
if (strwcmp(vdataname, VDA_NAME(vdata)) == 0)
break;
/* If the vgroup was not found, return peacefully. */
if (vdata == NULL)
return NULL;
/* Now that we have a pointer to the vdata, get the data associated */
/* with the record. */
return get_vdata(state, vdata);
}
/* get vgroup in group returns a pointer to the vgroup under the group with */
/* the proper name. The function requires the system state, a pointer to */
/* the group to be serarched, and the name of the vgroup to be checked. */
/* Returns the vgroup's pointer, NULL otherwise. */
/* CURRENTLY NOT USED */
Vgroup_t *GetVgroupInVgroup(state_t *state, Vgroup_t *group, char *name)
{
Vgroup_t *vgroup;
assert (group != NULL);
/* Look for the vgroup under the group with the proper name. */
/* Wildcarded names are accepted. */
for (vgroup = VGR_GROUPS(group); vgroup != NULL;
vgroup = VGR_SIBLING(vgroup))
{
if (strwcmp(name, VGR_NAME(vgroup)) == 0)
return vgroup;
}
return NULL;
}
/* set vgroup sets the active vgroup to the one located at the grouppath */
/* passed to the function. The group is located within the active file. */
/* If the group is found, the pointer to its memory-based copy is returned. */
/* If the group is not found in the file, the function returns NULL. */
Vgroup_t *set_vgroup(state_t *state, files_t *file, char *grouppath)
{
Vgroup_t *curr;
char *groupname;
char tmp[MAXPATHLEN];
/* If there is no active file, running this function is */
/* senseless. */
if (file == NULL) {
printf("[set_vgroup] WARNING: No active file set. Group not changed.\n");
return NULL;
}
/* If an empty group name is provided, then an error has occurred. */
if (*grouppath == '\0') {
printf("[set_vgroup] WARNING: No group specified. Group not changed.\n");
return NULL;
}
/* Copy the name of the grouppath so that we can modify it using */
/* strtok(). */
strcpy(tmp, grouppath);
groupname = tmp;
/* Ignore any leading slash. */
if (*groupname == '/') {
groupname++;
}
/* Set up the current Vgroup record pointer and the groupname for */
/* the first group. */
curr = file->groups;
groupname = strtok(groupname, "/");
while (groupname != NULL) {
/* If the group's children haven't been read in yet, do so. */
build_vgroup_children(state, curr);
/* Search current's group children for a group with the same */
/* name. */
for (curr = curr->groups; curr != NULL; curr = curr->sibling) {
if (strwcmp(groupname, curr->name) == 0) {
break;
}
}
/* If we didn't find a match among the children, then the */
/* path is bogus. */
if (curr == NULL) {
return NULL;
}
else {
groupname = strtok(NULL, "/");
}
}
/* Now that the group has been found, make sure that its children */
/* are read in. */
build_vgroup_children(state, curr);
#if 0
WIN_GROUP(win) = curr;
#endif
return curr;
}
/* build vgroup children reads into memory the records for the current */
/* vgroup's child vgroup and vdatas, if they haven't been read yet. The */
/* vgroup's children_read flag provides the cue. The function takes */
/* pointers to the system state and the current vgroup. Returns ST_OKAY */
/* if no errors occur. */
int build_vgroup_children(state_t *state, Vgroup_t *current)
{
VGROUP *vgptr;
VGROUP *vghandle;
VDATA *vdhandle;
int id;
int curr_id;
char name[MAXNAMELEN];
files_t *file;
/* Check that the vgroup is correctly connected to a file record. */
file = VGR_FILE(current);
if (file == NULL) {
printf("ERROR: Bad file reference in build_vgroup_children\n");
return ST_ERROR;
}
if (file->type != DTMPORT)
{
/* Make sure that we need to read in the children before we do */
/* anything. */
if (current->children_read == FALSE)
{
current->children_read = TRUE;
if (current->id == -1)
{
curr_id = Vgetid(file->fh, -1);
vgptr = NULL;
}
else
{
curr_id = current->id;
vgptr = Vattach(file->fh, curr_id, "r");
}
id = -1;
while ((id = GetNextId(file->fh,vgptr,id)) != -1)
{
if (IsVgroup(vgptr, id))
{
/* This item is a group. */
vghandle = Vattach(file->fh, id, "r");
Vgetname(vghandle, name);
Vdetach(vghandle);
add_vgroup(state, id, name, current);
}
else if (IsVdata(vgptr, id))
{
/* This item is a data. */
vdhandle = VSattach(file->fh, id, "r");
VSgetname(vdhandle, name); /*vdata name */
VSdetach(vdhandle);
add_vdata(state, id, name, current);
/* LATER... VSinquire(vshandle - vdata and field names */
}
else
{
printf("[build_vgroup_children] ERROR:\n %s %s\n",
"Unsupported data type encountered",
"in file");
return NULL;
}
}
}
}
return ST_OKAY;
}
/* Creates a new in-memory vgroup record and inserts it under the "parent" */
/* vgroup provided in the arguments. If parent is NULL, the new vgroup is */
/* linked as the first child of the active file. Returns a pointer to the */
/* new vgroup record, NULL if an error occurs. */
Vgroup_t *add_vgroup(state_t *state, int id, char *name, Vgroup_t *parent)
{
Vgroup_t *new;
Vgroup_t *curr;
/* Create a new Vgroup_t record and fill its fields with values */
/* passed to this function. */
new = create_vgroup(state, id, name);
/* Depending on the value of parent, link the record into a */
/* structure. */
/* This doesn't look like the new vgroup is ``linked as the first
child of the active file'' to me... */
if (parent == NULL)
{
printf("SYSTEM ERROR: parent NULL in add_vgroup.\n");
return NULL;
}
else
{
curr = parent->groups;
if (curr == NULL) {
/* Link the record as a child of the parent. */
parent->groups = new;
}
else
{
/* Find the last group and link the new record after it. */
while (curr->sibling != NULL)
curr = curr->sibling;
curr->sibling = new;
}
VGR_FILE(new) = VGR_FILE(parent);
}
return new;
}
/* Creates a new vdata with the specified name and id and inserts it as a */
/* of the parent. If parent is NULL, the vdata is made a child of the */
/* active file record. Returns a pointer to the new vdata record, NULL if */
/* an error occurs. */
Vdata_t *add_vdata(state_t *state, int id, char *name, Vgroup_t *parent)
{
Vdata_t *new;
/* Without a parent, the vdata cannot be linked in. */
assert (parent != NULL);
/* Create a new Vdata_t record and fill its fields with values */
/* passed to this function. */
new = create_vdata(state, id, name, VGR_FILE(parent));
/* Add the Vdata to the pool associated with this file. */
new->next = VGR_FILE(parent)->vdatas;
VGR_FILE(parent)->vdatas = new;
/* Insert the new vdata as the first child of the parent (assume */
/* that the order of vdatas is unimportant). */
new->sibling = parent->vdatas;
parent->vdatas = new;
return new;
}
/* Gets a pointer to the swapped-in vdata record. Returns a pointer to the */
/* record, NULL if an error occurs. */
Vdata_t *get_vdata(state_t *state, Vdata_t *vdata)
{
/* Check that a non-null vdata pointer is provided. */
/* For some reason this is always happening these days... */
if (vdata == NULL)
return NULL;
/* Just call swap_in. If the vdata is not already in memory, it */
/* will take care of it. */
if (swap_in(state, vdata) != ST_OKAY) {
printf("ERROR: Undable to swap in %s dataset.\n", vdata->name);
return NULL;
}
return vdata;
}
/* get vdata in group returns a pointer to the vdata under the group with */
/* the proper name. The function requires the system state, a pointer to */
/* the group to be serarched, and the name of the vdata to be checked. */
/* Returns the vdata's pointer, NULL otherwise. */
Vdata_t *get_vdata_in_vgroup(state_t *state, Vgroup_t *group, char *name)
{
Vdata_t *vdata;
assert (group != NULL);
/* Look for the vdata under the group with the proper name. */
/* Wildcarded names are accepted. */
for (vdata = VGR_VDATAS(group); vdata != NULL; vdata = VDA_SIBLING(vdata))
if (strwcmp(name, VDA_NAME(vdata)) == 0)
return vdata;
return NULL;
}
/* Returns a pointer to the file record associated with the file at */
/* fullpath. Returns NULL if an error occurs. */
files_t *find_file (state_t *state, int type, char *fullpath)
{
char filepath[MAXLINELEN];
long portid;
files_t *file;
if (type == DTMPORT)
{
/* Check that there is a colon. Must be of the form: */
/* [host]:portid */
/* where 1024 < portid <= 65536 */
if ((sscanf(fullpath, ":%ld", &portid) != 1) &&
(sscanf(fullpath, "%*[^:]:%ld", &portid) != 1))
{
bprintf(state, "ERROR: Colon required in port name.\n");
return NULL;
}
else
{
if ((portid < 1024) || (portid > 65536))
{
bprintf(state, "ERROR: Port ID must be between ");
bprintf(state, "1024 and 65536.\n");
return NULL;
}
strcpy(filepath, fullpath);
}
}
else
{
/* Check that we have a legal file pathname. */
if (parse_path(state, fullpath, FILEPATH, filepath,
NULL, NULL) == ST_ERROR)
{
bprintf(state, "ERROR: Illegal file name '%s'.\n", fullpath);
return NULL;
}
}
/* Set the state to that file. */
if ( (file = set_file(state, type, filepath)) == NULL )
{
stprintf(state, "ERROR: Problem reading file %s.\n", filepath);
/* It would seem that we don't need to have a dialog here... */
return NULL;
}
/* Return the pointer to the file record that was found. */
return file;
}
/* Returns a pointer to the vgroup at fullpath. fullpath is the name of a */
/* vgroup, which may include a filename. The difference between this */
/* and get_vdata_in_group is mysterious. */
Vgroup_t *find_vgroup(state_t *state, files_t *file, char *fullpath)
{
Vgroup_t *vgroup;
if (file == NULL)
{
bprintf(state, "[find_vgroup] ERROR: Must choose a file first.\n");
return NULL;
}
/* If a vgroup name was specified, set the state to that vgroup. */
if ( (vgroup = set_vgroup(state, file, fullpath)) == NULL)
return NULL;
/* Return a pointer to the vgroup that was chosen. */
return vgroup;
}
/* Swaps a vdata's information into memory if it is not already in memory. */
/* Updates the "last_used" time accordingly. Recalculates the data set's */
/* statistics, if necessary. Returns ST_OKAY if no errors occur. */
int swap_in(state_t *state, Vdata_t *vdata)
{
VDATA *vdhandle;
char name[MAXNAMELEN];
char fields[MAXNAMELEN];
int32 nv, interlace, vsize, forder, ftype, nfields;
int16 *buff;
int i;
/* If this a bad vdata pointer, quit the function. */
assert (vdata != NULL);
/* Is the data already in memory? */
if (vdata->in_memory == TRUE)
{
/* All we need to do is update the last used time. */
/* WHAT FOR? This isn't used anywhere else in the code. */
vdata->last_used = state->redraw_count;
}
else
{
/* The data has not been read in yet. Read it in. */
/* Hook up to the data. */
vdhandle = VSattach (vdata->file->fh, vdata->id, "r");
VSinquire (vdhandle, &nv, &interlace, fields, &vsize, name);
VSsetfields(vdhandle, fields);
nfields = VFnfields(vdhandle);
ftype = VFfieldtype(vdhandle, 0);
for (i=0, forder = 0; i< nfields; i++)
forder += VFfieldorder(vdhandle, i);
#if 0
stprintf
(state, "Reading %s:%s ...\n", vdata->file->path, VDA_NAME(vdata));
#endif
if (ftype == DFNT_INT16 && sizeof(int16) < sizeof(int)) {
buff = (int16 *)malloc(nv * vsize);
if (buff == NULL)
{
fprintf(stderr, "[swap_in] ERROR: Cannot perform malloc.\n");
fflush (stderr);
return ST_ERROR;
}
if (VSread(vdhandle, (unsigned char *)buff, nv, interlace) == -1)
{
fprintf(stderr, "[swap_in] ERROR: Problem during read.\n");
fflush (stderr);
return ST_ERROR;
}
vsize *= 2;
vdata->data = (char *) PVMALLOC(nv * vsize * sizeof (char));
if (vdata->data == NULL)
{
fprintf(stderr, "[swap_in] ERROR: Cannot perform malloc.\n");
fflush (stderr);
return ST_ERROR;
}
for (i = 0; i < nv*forder; i++)
*((int *)vdata->data+i) = buff[i];
free(buff);
}
else {
vdata->data = (char *) PVMALLOC(nv * vsize * sizeof (char));
if (vdata->data == NULL)
{
fprintf(stderr, "[swap_in] ERROR: Cannot perform malloc.\n");
fflush (stderr);
return ST_ERROR;
}
if (VSread(vdhandle, (unsigned char *)vdata->data, nv, interlace) ==
-1)
{
fprintf(stderr, "[swap_in] ERROR: Problem during read.\n");
fflush (stderr);
return ST_ERROR;
}
}
VSdetach(vdhandle);
vdata->in_memory = TRUE;
/* What is rec_count/rec_size/rec_type doing
in stats[0]??? This is a silly hack. */
vdata->stats[0].rec_count = nv;
vdata->stats[0].rec_size = vsize / sizeof(int);
/* KLUDGE! -- This does not check for other data types. */
/* If the record is larger than one element, then assume */
/* that it is PVINTEGER, otherwise, assume PVFLOAT. */
/* BOY, this is stupid. */
if (vsize > sizeof(int) && ftype != DFNT_FLOAT32)
vdata->stats[0].type = PVINTEGER;
else
vdata->stats[0].type = PVFLOAT;
if (!(vdata->stats_read))
calc_stats(state, vdata);
}
return ST_OKAY;
}
/* Calculates the min, mean, max, and variance of a given vdata, storing the */
/* statistics in the record. Returns ST_OKAY. */
int calc_stats(state_t *state, Vdata_t *vdata)
{
int i, j, n, m;
int *iptr;
register int ival;
long imin[MAXDATADIMS], imax[MAXDATADIMS];
long imean[MAXDATADIMS], imeansq[MAXDATADIMS];
float *fptr;
register float fval;
double fmin[MAXDATADIMS], fmax[MAXDATADIMS];
double fmean[MAXDATADIMS], fmeansq[MAXDATADIMS];
m = vdata->stats[0].rec_size;
n = vdata->stats[0].rec_count;
PVD (("+++ [calc_stats] vdata is %s\n", vdata->name));
PVD (("[calc_stast] rec_size is %d, rec_count is %d\n", m, n));
switch (vdata->stats[0].type)
{
case PVINTEGER:
PVD ((" [cs] Processing PVINTEGER.\n"));
for (j = 0; j < m; j++)
{
imin[j] = MAXLONG;
imax[j] = -MAXLONG;
imean[j] = 0;
imeansq[j] = 0;
}
for (i = n, iptr = (int *) vdata->data; i > 0; i--)
{
for (j = 0; j < m; j++, iptr++)
{
ival = *iptr;
imin[j] = MIN(imin[j], ival);
imax[j] = MAX(imax[j], ival);
imean[j] += ival;
imeansq[j] += ival*ival;
}
}
for (j = 0; j < m; j++)
{
PVD ((" [cs] New min/max is %d/%d\n", imin[j], imax[j]));
fmean[j] = ((float) imean[j]) / n;
fmeansq[j] = ((float) imeansq[j]) / n;
vdata->stats[j].min = (float) imin[j];
vdata->stats[j].max = (float) imax[j];
vdata->stats[j].mean = fmean[j];
vdata->stats[j].mean_sq = fmeansq[j];
vdata->stats[j].variance = fmeansq[j]-fmean[j]*fmean[j];
}
break;
case PVFLOAT:
for (j = 0; j < m; j++)
{
fmin[j] = MAXDOUBLE;
fmax[j] = -MAXDOUBLE;
fmean[j] = 0.0;
fmeansq[j] = 0.0;
}
for (i = n, fptr = (float *) vdata->data; i > 0; i--)
{
for (j = 0; j < m; j++, fptr++)
{
fval = *fptr;
fmin[j] = MIN(fmin[j], fval);
fmax[j] = MAX(fmax[j], fval);
fmean[j] += fval;
fmeansq[j] += fval*fval;
}
}
for (j = 0; j < m; j++)
{
fmean[j] /= n;
fmeansq[j] /= n;
vdata->stats[j].min = fmin[j];
vdata->stats[j].max = fmax[j];
vdata->stats[j].mean = fmean[j];
vdata->stats[j].mean_sq = fmeansq[j];
vdata->stats[j].variance = fmeansq[j]-fmean[j]*fmean[j];
}
break;
default:
fprintf(stderr, "[calc_data] SYSTEM ERROR: Unsupported data type %d.\n",
vdata->stats[0].type);
fflush (stderr);
break;
}
/* Set the flag so that we do not do this again. */
vdata->stats_read = TRUE;
PVD (("[calc_stats] min is %f max is %f\n",
vdata->stats[0].min, vdata->stats[0].max));
return ST_OKAY;
}
int combine_stats(state_t *state, stats_t updstat[MAXDATADIMS][MAXVDATAS],
stats_t newstat[MAXDATADIMS][MAXVDATAS])
{
stats_t *upd, *new;
int i,j;
for (i = 0; i < MAXDATADIMS; i++)
{
for (j = 0; j < MAXVDATAS; j++)
{
upd = &updstat[i][j];
new = &newstat[i][j];
assert ((upd != NULL) && (new != NULL));
upd->type = new->type;
upd->rec_size = new->rec_size;
PVD (("[combine_stats] &&&&&&&&& rec_size 1 is %d, 2 is %d\n",
new->rec_size, upd->rec_size));
upd->rec_count = new->rec_count;
upd->min = MIN(upd->min, new->min);
upd->max = MAX(upd->max, new->max);
upd->mean = (upd->mean + new->mean)/2;
upd->mean_sq = (upd->mean_sq + new->mean_sq)/2;
upd->variance = upd->mean_sq - (upd->mean * upd->mean);
}
}
return ST_OKAY;
}
/* ------------------------------------------------------------------------ */
/* ---------------------------- dump functions ---------------------------- */
/* ------------------------------------------------------------------------ */
static int dump_data(int i, Vdata_t *data)
{
int j, k;
for ( ; data != NULL; data = data->sibling)
{
for (k = 0; k < data->stats[0].rec_size; k++)
{
for (j=i; j > 0; j--)
printf(" ");
if (k == 0) {
printf("DATA: %c%-6s",
(data->in_memory)?'*':' ', data->name);
}
else if (data->in_memory)
{
printf("%13s", "");
}
if (data->in_memory)
{
printf(" %02d %c %5d %1d %.2f %.2f %.2f %lx\n",
data->id,
(data->stats[0].type == PVINTEGER)?
'I' : 'F',
data->stats[0].rec_count,
data->stats[0].rec_size,
data->stats[k].min,
data->stats[k].mean,
data->stats[k].max,
(long) data);
}
else
{
printf("\n");
}
}
}
return ST_OKAY;
}
static int dump_groups(int i, Vgroup_t *group)
{
int j;
for (j = i; j > 0; j--)
printf(" ");
printf("[dump_groups] GROUP: %s\n", group->name);
dump_data(i+1, group->vdatas);
for (group = group->groups; group != NULL; group = group->sibling)
dump_groups(i+1, group);
return ST_OKAY;
}
int dump_files(state_t *state)
{
files_t *file;
for (file = state->files; file != NULL; file = file->next)
{
printf("[dump_files] FILE: %s\n", file->path);
/* Recurse here: */
dump_groups(1, file->groups);
}
return ST_OKAY;
}